package gameCard

import (
	"common/utils"
	"context"
	"core/models/db"
	"core/service"
	"encoding/json"
	"sync"
)

type Logic struct {
	sync.RWMutex
	cards       map[CardType][]Card //牌库
	gameID      uint
	gameService *service.GameService
}

func (l *Logic) handlerCards() {
	l.Lock()
	defer l.Unlock()
	gameCard := l.gameService.GameCard(context.TODO(), l.gameID)
	//组装卡牌数据
	l.assembleData(gameCard)
	//洗牌
	go l.washCards()
}

func (l *Logic) assembleData(data *[]db.GameCard) {
	for _, v := range *data {
		for i := 1; i <= v.Num; i++ {
			var additionalAttack, AdditionalBlood, level int64
			if v.Type == 3 || v.Type == 4 {
				additionalAttack = v.Attack
				AdditionalBlood = v.Blood
			} else if v.Type == 1 {
				level = 1
			}
			card := Card{
				CardID:              v.ID,
				CardIDTypeID:        i,
				CardName:            v.Name,
				CardImg:             v.Img,
				CardDesc:            v.Desc,
				CardType:            CardType(v.Type),
				Attack:              v.Attack,
				AdditionalAttack:    additionalAttack,
				TotalAttack:         v.Attack,
				Blood:               v.Blood,
				AdditionalBlood:     AdditionalBlood,
				TotalBlood:          v.Blood + AdditionalBlood,
				SurplusBlood:        v.Blood,
				Potential:           v.Potential,
				AdditionalPotential: 0,
				TotalPotential:      v.Potential,
				Price:               v.Price,
				LinkType:            CardType(v.LinkType),
				Consume:             v.Consume,
				Level:               level,
				Star:                0,
			}
			l.cards[CardType(v.Type)] = append(l.cards[CardType(v.Type)], card)
		}
	}
}

// washCards 洗牌
func (l *Logic) washCards() {
	l.Lock()
	defer l.Unlock()
	//将卡牌打乱顺序
	for cardType, v := range l.cards {
		if cardType == Evolution || cardType == Upgrade {
			continue
		}
		for i := len(v) - 1; i > 0; i-- {
			j := utils.Rands(i + 1)
			v[i], v[j] = v[j], v[i]
		}
		l.cards[cardType] = v
	}
}

// getRefreshCards 发牌
func (l *Logic) getRefreshCards(level int64, num int) []RefreshCard {
	// 发牌之后 牌就没了
	l.Lock()
	defer l.Unlock()
	var cards []RefreshCard
	for i := 0; i < num; i++ {
		randsLevel := utils.Random(1, int(level))
		if num == 1 {
			randsLevel = level
		}
		if len(l.cards[CardType(randsLevel)]) < num {
			randsLevel = 1
		}
		if len(l.cards[CardType(randsLevel)]) <= 0 {
			randsLevel = 1
		}
		//logs.Warn("卡牌%v,随机的牌是%d", l.cards, randsLevel)
		card := l.cards[CardType(randsLevel)][0]
		refreshCard := RefreshCard{
			Card:  card,
			IsBuy: false,
		}
		l.cards[CardType(randsLevel)] = l.cards[CardType(randsLevel)][1:]
		cards = append(cards, refreshCard)
	}
	return cards
}

// cardsReturn 退牌
func (l *Logic) cardsReturn(refresh []RefreshCard) {
	l.Lock()
	defer l.Unlock()
	for _, v := range refresh {
		if v.IsBuy {
			continue
		}
		l.cards[v.Card.CardType] = append(l.cards[v.Card.CardType], v.Card)
	}
	go l.washCards()
}

// retreatHandCard 退手牌
func (l *Logic) retreatHandCard(card Card) {
	l.Lock()
	defer l.Unlock()
	if card.Star > 0 {
		card.Attack = card.Attack / 2
		card.Blood = card.Blood / 2
		card.Potential = card.Potential / 2
	}
	card.AdditionalAttack = 0
	card.TotalAttack = card.Attack
	card.AdditionalBlood = 0
	card.TotalBlood = card.Blood
	card.SurplusBlood = card.Blood
	card.AdditionalPotential = 0
	card.TotalPotential = card.Potential
	if card.CardType == 1 {
		card.Level = 1
		card.Star = 0
	}
	l.cards[card.CardType] = append(l.cards[card.CardType], card)
	go l.washCards()
}

// retreatHandCards 退手牌
func (l *Logic) retreatHandCards(cards []Card) {
	l.Lock()
	defer l.Unlock()
	for _, card := range cards {
		if card.Star > 0 {
			card.Attack = card.Attack / 2
			card.Blood = card.Blood / 2
			card.Potential = card.Potential / 2
		}
		card.AdditionalAttack = 0
		card.TotalAttack = card.Attack
		card.AdditionalBlood = 0
		card.TotalBlood = card.Blood
		card.SurplusBlood = card.Blood
		card.AdditionalPotential = 0
		card.TotalPotential = card.Potential
		if card.CardType == 1 {
			card.Level = 1
			card.Star = 0
		}
		l.cards[card.CardType] = append(l.cards[card.CardType], card)
	}
	go l.washCards()
}

func (l *Logic) retreatSiteCard(card MonstersCard) {
	l.Lock()
	defer l.Unlock()
	if card.Star > 0 {
		card.Attack = card.Attack / 2
		card.Blood = card.Blood / 2
		card.Potential = card.Potential / 2
	}
	card.AdditionalAttack = 0
	card.TotalAttack = card.Attack
	card.AdditionalBlood = 0
	card.TotalBlood = card.Blood
	card.SurplusBlood = card.Blood
	card.AdditionalPotential = 0
	card.TotalPotential = card.Potential
	if card.CardType == 1 {
		card.Level = 1
		card.Star = 0
	}
	l.cards[card.CardType] = append(l.cards[card.CardType], card.Card)
	if card.Arms.CardID != 0 {
		l.cards[card.Arms.CardType] = append(l.cards[card.Arms.CardType], card.Arms)
	}
	if card.Defense.CardID != 0 {
		l.cards[card.Defense.CardType] = append(l.cards[card.Defense.CardType], card.Defense)
	}
	for _, v := range card.UpCard {
		l.cards[v.CardType] = append(l.cards[v.CardType], v)
	}
	if card.Evolution.Monsters.CardID != 0 {
		if card.Evolution.Monsters.Star > 0 {
			card.Evolution.Monsters.Attack = card.Attack / 2
			card.Evolution.Monsters.Blood = card.Blood / 2
			card.Evolution.Monsters.Potential = card.Potential / 2
		}
		card.Evolution.Monsters.AdditionalAttack = 0
		card.Evolution.Monsters.TotalAttack = card.Attack
		card.Evolution.Monsters.AdditionalBlood = 0
		card.Evolution.Monsters.TotalBlood = card.Blood
		card.Evolution.Monsters.SurplusBlood = card.Blood
		card.Evolution.Monsters.AdditionalPotential = 0
		card.Evolution.Monsters.TotalPotential = card.Potential
		l.cards[card.Evolution.Monsters.CardType] = append(l.cards[card.Evolution.Monsters.CardType], card.Evolution.Monsters)
		if card.Evolution.Monsters.CardType == 1 {
			card.Evolution.Monsters.Level = 1
			card.Evolution.Monsters.Star = 0
		}
	}
	if card.Evolution.Upgrade.CardID != 0 {
		l.cards[card.Evolution.Upgrade.CardType] = append(l.cards[card.Evolution.Upgrade.CardType], card.Evolution.Upgrade)
	}
	for _, v := range card.Evolution.UpCard {
		l.cards[v.CardType] = append(l.cards[v.CardType], v)
	}
	go l.washCards()
}

func (l *Logic) retreatSiteCards(cards []MonstersCard) {
	l.Lock()
	defer l.Unlock()
	for _, card := range cards {
		if card.Star > 0 {
			card.Attack = card.Attack / 2
			card.Blood = card.Blood / 2
			card.Potential = card.Potential / 2
		}
		card.AdditionalAttack = 0
		card.TotalAttack = card.Attack
		card.AdditionalBlood = 0
		card.TotalBlood = card.Blood
		card.SurplusBlood = card.Blood
		card.AdditionalPotential = 0
		card.TotalPotential = card.Potential
		if card.CardType == 1 {
			card.Level = 1
			card.Star = 0
		}
		l.cards[card.CardType] = append(l.cards[card.CardType], card.Card)
		if card.Arms.CardID != 0 {
			l.cards[card.Arms.CardType] = append(l.cards[card.Arms.CardType], card.Arms)
		}
		if card.Defense.CardID != 0 {
			l.cards[card.Defense.CardType] = append(l.cards[card.Defense.CardType], card.Defense)
		}
		for _, v := range card.UpCard {
			l.cards[v.CardType] = append(l.cards[v.CardType], v)
		}
		if card.Evolution.Monsters.CardID != 0 {
			if card.Evolution.Monsters.Star > 0 {
				card.Evolution.Monsters.Attack = card.Attack / 2
				card.Evolution.Monsters.Blood = card.Blood / 2
				card.Evolution.Monsters.Potential = card.Potential / 2
			}
			card.Evolution.Monsters.AdditionalAttack = 0
			card.Evolution.Monsters.TotalAttack = card.Attack
			card.Evolution.Monsters.AdditionalBlood = 0
			card.Evolution.Monsters.TotalBlood = card.Blood
			card.Evolution.Monsters.SurplusBlood = card.Blood
			card.Evolution.Monsters.AdditionalPotential = 0
			card.Evolution.Monsters.TotalPotential = card.Potential
			if card.Evolution.Monsters.CardType == 1 {
				card.Evolution.Monsters.Level = 1
				card.Evolution.Monsters.Star = 0
			}
			l.cards[card.Evolution.Monsters.CardType] = append(l.cards[card.Evolution.Monsters.CardType], card.Evolution.Monsters)
		}
		if card.Evolution.Upgrade.CardID != 0 {
			l.cards[card.Evolution.Upgrade.CardType] = append(l.cards[card.Evolution.Upgrade.CardType], card.Evolution.Upgrade)
		}
		for _, v := range card.Evolution.UpCard {
			l.cards[v.CardType] = append(l.cards[v.CardType], v)
		}
	}
	go l.washCards()
}

func (l *Logic) EndGame(users *[]EndGameUsers, roomID string, total int64, peopleNum int, champion float64, runner float64, thirdPlace float64) {
	ctx := context.TODO()
	marshal, _ := json.Marshal(users)
	_ = l.gameService.EndGameCard(ctx, marshal, roomID, total, peopleNum, champion, runner, thirdPlace)
}

func (l *Logic) End(uid uint, roomID string) {
	ctx := context.TODO()
	_ = l.gameService.EndGameCardOne(ctx, uid, roomID)
}

func NewLogic(gameService *service.GameService, gameID uint) *Logic {
	return &Logic{
		cards:       make(map[CardType][]Card, 0),
		gameID:      gameID,
		gameService: gameService,
	}
}
